<?php

namespace YaPing\SDK;

use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

class YaPingException extends Exception
{
}

class ConfigException extends YaPingException
{
}

class ValidationException extends YaPingException
{
}

class APIException extends YaPingException
{
    private int $errorCode;

    public function __construct(int $code, string $message)
    {
        parent::__construct($message);
        $this->errorCode = $code;
    }

    public function getErrorCode(): int
    {
        return $this->errorCode;
    }
}

class YaPingClient
{
    private string $appId;
    private string $appSecret;
    private string $baseUrl;
    private Client $client;

    /**
     * YaPingClient constructor.
     * @param string $appId
     * @param string $appSecret
     * @param string|null $baseUrl
     * @throws ConfigException
     */
    public function __construct(string $appId, string $appSecret, ?string $baseUrl = null)
    {
        if (empty($appId) || empty($appSecret)) {
            throw new ConfigException('APP_ID and APP_SECRET are required');
        }

        $this->appId = $appId;
        $this->appSecret = $appSecret;
        $this->baseUrl = rtrim($baseUrl ?? 'https://mp-api.66-six.com', '/');
        $this->client = new Client([
            'base_uri' => $this->baseUrl,
            'timeout' => 30,
            'http_errors' => false
        ]);
    }

    /**
     * 加密数据
     * @param string $data
     * @return string
     */
    private function encrypt(string $data): string
    {
        $cipher = "AES-256-ECB";
        $data = openssl_encrypt($data, $cipher, $this->appSecret, OPENSSL_RAW_DATA);
        return base64_encode($data);
    }

    /**
     * 发送请求
     * @param string $endpoint
     * @param array $data
     * @return array
     * @throws APIException
     * @throws GuzzleException
     */
    private function makeRequest(string $endpoint, array $data = []): array
    {
        $jsonData = json_encode($data);
        if ($jsonData === false) {
            throw new APIException(500, 'Failed to encode request data');
        }

        $encryptedData = $this->encrypt($jsonData);
        $response = $this->client->post($endpoint, [
            'json' => [
                'app_id' => $this->appId,
                'json_data' => $encryptedData
            ]
        ]);

        $responseData = json_decode($response->getBody()->getContents(), true);
        if (!isset($responseData['success']) || !$responseData['success']) {
            throw new APIException(
                $responseData['code'] ?? 500,
                $responseData['message'] ?? 'Unknown error'
            );
        }

        return $responseData['data'] ?? $responseData;
    }

    /**
     * 商品选号接口
     * @param int $goodsId
     * @return array
     * @throws APIException
     * @throws GuzzleException
     */
    public function getCard(int $goodsId): array
    {
        return $this->makeRequest('/open/api/get_card', [
            'goods_id' => $goodsId
        ]);
    }

    /**
     * 订单查询接口
     * @param string|null $orderSn
     * @param int $page
     * @param int $pageSize
     * @return array
     * @throws APIException
     * @throws GuzzleException
     */
    public function listOrder(?string $orderSn = null, int $page = 1, int $pageSize = 10): array
    {
        $data = [
            'page' => $page,
            'page_size' => $pageSize
        ];

        if ($orderSn !== null) {
            $data['order_sn'] = $orderSn;
        }

        return $this->makeRequest('/open/api/list_order', $data);
    }

    /**
     * 提交订单接口
     * @param array $params
     * @return array
     * @throws APIException
     * @throws ValidationException
     * @throws GuzzleException
     */
    public function pushOrder(array $params): array
    {
        $requiredFields = [
            'goods_id', 'select_mobile', 'name', 'card', 'mobile',
            'province_code', 'province', 'city_code', 'city',
            'district_code', 'district', 'address'
        ];

        foreach ($requiredFields as $field) {
            if (!isset($params[$field]) || empty($params[$field])) {
                throw new ValidationException("Missing required field: {$field}");
            }
        }

        // 验证姓名是否为中文
        if (!preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $params['name'])) {
            throw new ValidationException('Name must be in Chinese');
        }

        return $this->makeRequest('/open/api/push_order', $params);
    }

    /**
     * 验证回调URL
     * @param string $url
     * @return bool
     * @throws ValidationException
     */
    public function verifyCallback(string $url): bool
    {
        if (!filter_var($url, FILTER_VALIDATE_URL) || 
            !preg_match('/^https?:\/\//i', $url)) {
            throw new ValidationException('Invalid callback URL format');
        }
        return true;
    }
}
